//
//  ChatDemoHelper.m
//  ChatDemo-UI3.0
//
//  Created by EaseMob on 15/12/8.
//  Copyright © 2015年 EaseMob. All rights reserved.
//

#import "ChatDemoHelper.h"

#import "ApplyViewController.h"
#import "CallViewController.h"
#import "RomensSDK/UIViewController+HUD.h"
#import "TTGlobalUICommon.h"
#import <Hyphenate/EMClient+Call.h>
#import "EMCDDeviceManager+Remind.h"
#import "HXRuntimeStatus.h"
#import "HXDDUserEntity.h"
@interface ChatDemoHelper()
{
    NSTimer *_callTimer;
}
@property (strong, nonatomic) NSDate *lastPlaySoundDate;

@end

static ChatDemoHelper *helper = nil;

@implementation ChatDemoHelper

+ (instancetype)shareHelper
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        helper = [[ChatDemoHelper alloc] init];
    });
    return helper;
}

- (void)dealloc
{
    [[EMClient sharedClient] removeDelegate:self];
    [[EMClient sharedClient].groupManager removeDelegate:self];
    [[EMClient sharedClient].contactManager removeDelegate:self];
    [[EMClient sharedClient].roomManager removeDelegate:self];
    [[EMClient sharedClient].chatManager removeDelegate:self];
    [[EMClient sharedClient].callManager removeDelegate:self];
}

- (id)init
{
    self = [super init];
    if (self) {
        [self initHelper];
    }
    return self;
}

- (void)initHelper
{
    [[EMClient sharedClient] addDelegate:self delegateQueue:nil];
    [[EMClient sharedClient].groupManager addDelegate:self delegateQueue:nil];
    [[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];
    [[EMClient sharedClient].roomManager addDelegate:self delegateQueue:nil];
    [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];
#pragma mark--call
    self.callLock = [[NSObject alloc] init];
    [[EMClient sharedClient].callManager addDelegate:self delegateQueue:nil];
    
    NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"calloptions.data"];
    EMCallOptions *options = nil;
    if ([[NSFileManager defaultManager] fileExistsAtPath:file]) {
        options = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
    } else {//上面的那个文件不存在，所以这个方法也不走。因为环信的设置界面不存在。。。
        options = [[EMClient sharedClient].callManager getCallOptions];//获取设置项
        options.isSendPushIfOffline = NO;
    }
    [[EMClient sharedClient].callManager setCallOptions:options];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(makeCall:) name:KNOTIFICATION_CALL object:nil];
}

- (void)asyncPushOptions
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        EMError *error = nil;
        [[EMClient sharedClient] getPushOptionsFromServerWithError:&error];
    });
}

- (void)asyncGroupFromServer
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [[EMClient sharedClient].groupManager getJoinedGroups];
        EMError *error = nil;
        [[EMClient sharedClient].groupManager getMyGroupsFromServerWithError:&error];
    });
}

- (void)asyncConversationFromDB
{
    __weak typeof(self) weakself = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSArray *array = [[EMClient sharedClient].chatManager getAllConversations];
        [array enumerateObjectsUsingBlock:^(EMConversation *conversation, NSUInteger idx, BOOL *stop){
            if(conversation.latestMessage == nil){
                [[EMClient sharedClient].chatManager deleteConversation:conversation.conversationId isDeleteMessages:NO completion:nil];
            }
        }];
        dispatch_async(dispatch_get_main_queue(), ^{
            if (weakself.conversationListVC) {
                [weakself.conversationListVC refreshDataSource];
            }
            
            [[NSNotificationCenter defaultCenter] postNotificationName:UnReadMsgsNotificationName object:nil];
//            [self setupUnreadMessageCount];
        });
    });
}

#pragma mark - EMClientDelegate

// 网络状态变化回调
- (void)didConnectionStateChanged:(EMConnectionState)connectionState
{
//    [self networkChanged:connectionState];
    [self.conversationListVC networkChanged:connectionState];
    [self.chatVC networkChanged:connectionState];
}
//- (void)networkChanged:(EMConnectionState)connectionState
//{
//    _connectionState = connectionState;
//    [self.conversationListVC networkChanged:connectionState];
//}

- (void)didAutoLoginWithError:(EMError *)error
{
    if (error) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"自动登录失败，请重新登录" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
        alertView.tag = 100;
        [alertView show];
    } else if([[EMClient sharedClient] isConnected]){
       
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            BOOL flag = [[EMClient sharedClient] migrateDatabaseToLatestSDK];
            if (flag) {
                [self asyncGroupFromServer];
                [self asyncConversationFromDB];
            }
//            dispatch_async(dispatch_get_main_queue(), ^{
//            });
        });
    }
}
//已在其他地方登录。当前登录账号在其它设备登录时会接收到此回调
- (void)userAccountDidLoginFromOtherDevice
{
    [self _clearHelper];
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:NSLocalizedString(@"loginAtOtherDevice", @"your login account has been in other places") delegate:self cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
    [alertView show];
#pragma mark ---用户其他设备登录，取消自动登录---
//    [[NSUserDefaults standardUserDefaults] setObject:@"0" forKey:@"isAutologin"];
    [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_LOGINCHANGE object:@NO];
}
//当前登录账号已经被从服务器端删除时会收到该回调
- (void)userAccountDidRemoveFromServer
{
    [self _clearHelper];
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:NSLocalizedString(@"loginUserRemoveFromServer", @"your account has been removed from the server side") delegate:self cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
    [alertView show];
    [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_LOGINCHANGE object:@NO];
}
//服务被禁用
//- (void)userDidForbidByServer
//{
//    [self _clearHelper];
//    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:NSLocalizedString(@"servingIsBanned", @"Serving is banned") delegate:self cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
//    [alertView show];
//    [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_LOGINCHANGE object:@NO];
//}
//- (void)didServersChanged
//{
//    [self _clearHelper];
//    [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_LOGINCHANGE object:@NO];
//}
//
//- (void)didAppkeyChanged
//{
//    [self _clearHelper];
//    [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_LOGINCHANGE object:@NO];
//}

#pragma mark - EMChatManagerDelegate
//会话列表发生变化
- (void)conversationListDidUpdate:(NSArray *)aConversationList
{
    //tabBar刷新未读消息数量
    [[NSNotificationCenter defaultCenter] postNotificationName:UnReadMsgsNotificationName object:nil];
//    [self setupUnreadMessageCount];
    
    if (self.conversationListVC) {
        [_conversationListVC refreshDataSource];
    }
}


- (void)didReceiveMessages:(NSArray *)aMessages
{
    BOOL isRefreshCons = YES;
    for(EMMessage *message in aMessages){
        BOOL needShowNotification = (message.chatType != EMChatTypeChat) ? [self _needShowNotification:message.conversationId] : YES;
        if (needShowNotification) {
            UIApplicationState state = [[UIApplication sharedApplication] applicationState];
            switch (state) {
                case UIApplicationStateActive:
                    if (![self isSlientForMessageFromUser:message.from]) {
                        [self playSoundAndVibration];
                    }
                    break;
                case UIApplicationStateInactive:
                    if (![self isSlientForMessageFromUser:message.from]) {
                        [self playSoundAndVibration];
                    }
                    break;
                case UIApplicationStateBackground:
                    [self showNotificationWithMessage:message];
                    break;
                default:
                    break;
            }
        }
        
        if (_chatVC == nil) {
            _chatVC = [self _getCurrentChatView];
        }
        BOOL isChatting = NO;
        if (_chatVC) {
            isChatting = [message.conversationId isEqualToString:_chatVC.conversation.conversationId];
        }
        if (_chatVC == nil || !isChatting) {
            
            if (self.conversationListVC) {
                [_conversationListVC refresh];
            }
            
            //重新获取未读消息
            [[NSNotificationCenter defaultCenter] postNotificationName:UnReadMsgsNotificationName object:nil];
//            [self setupUnreadMessageCount];
            return;
        }
        
        if (isChatting) {
            isRefreshCons = NO;
        }
    }
    
    if (isRefreshCons) {
        if (self.conversationListVC) {
            [_conversationListVC refresh];
        }
        
        [[NSNotificationCenter defaultCenter] postNotificationName:UnReadMsgsNotificationName object:nil];
//        [self setupUnreadMessageCount];
    }
}
//Cmd消息类似一种指令型的消息。比如您的服务器要通知客户端做某些操作，您可以服务器和客户端提前约定好某个字段，当客户端收到约定好的字段时，执行某种特殊操作。
- (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages
{
    //tabBar弹出提示
    if (self.mainVC) {
        [_mainVC showHint:NSLocalizedString(@"receiveCmd", @"receive cmd message")];//发现新数据...
        //自定义协议
        if ([self.helperDelegate respondsToSelector:@selector(cmdMessagesReceived)]) {
            [self.helperDelegate cmdMessagesReceived];
        }
    }
    for (EMMessage *message in aCmdMessages) {
        EMCmdMessageBody *cmdBody = (EMCmdMessageBody *)message.body;
        NSString *action = cmdBody.action;
        if ([action isEqualToString:@"inviteToJoinConference"]) {
            //            NSString *callId = [message.ext objectForKey:@"callId"];
        } else if ([action isEqualToString:@"__Call_ReqP2P_ConferencePattern"]) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"已转为会议模式" delegate:self cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
            [alertView show];
        }
    }
}
#pragma mark - EMGroupManagerDelegate 群组
//离开群组回调
- (void)didReceiveLeavedGroup:(EMGroup *)aGroup
                       reason:(EMGroupLeaveReason)aReason
{
    NSString *str = nil;
    if (aReason == EMGroupLeaveReasonBeRemoved) {
        str = [NSString stringWithFormat:@"你被管理员移除该群: [%@]", aGroup.subject];
    } else if (aReason == EMGroupLeaveReasonDestroyed) {
        str = [NSString stringWithFormat:@"管理员解散了该群: [%@]", aGroup.subject];
    }
    
    if (str.length > 0) {
        TTAlertNoTitle(str);
    }
    
    NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:_mainVC.navigationController.viewControllers];
    ChatViewController *chatViewContrller = nil;
    for (id viewController in viewControllers)
    {
        if ([viewController isKindOfClass:[ChatViewController class]] && [aGroup.groupId isEqualToString:[(ChatViewController *)viewController conversation].conversationId])
        {
            chatViewContrller = viewController;
            break;
        }
    }
    if (chatViewContrller)
    {
        [viewControllers removeObject:chatViewContrller];
        if ([viewControllers count] > 0) {
            [_mainVC.navigationController setViewControllers:@[viewControllers[0]] animated:YES];
        } else {
            [_mainVC.navigationController setViewControllers:viewControllers animated:YES];
        }
    }
}
//群组的群主收到用户的入群申请，群的类型是EMGroupStylePublicJoinNeedApproval
- (void)didReceiveJoinGroupApplication:(EMGroup *)aGroup
                             applicant:(NSString *)aApplicant
                                reason:(NSString *)aReason
{
    if (!aGroup || !aApplicant) {
        return;
    }
    
    if (!aReason || aReason.length == 0) {
        aReason = [NSString stringWithFormat:NSLocalizedString(@"group.applyJoin", @"%@ apply to join groups\'%@\'"), aApplicant, aGroup.subject];
    }
    else{
        aReason = [NSString stringWithFormat:NSLocalizedString(@"group.applyJoinWithName", @"%@ apply to join groups\'%@\'：%@"), aApplicant, aGroup.subject, aReason];
    }
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:@{@"title":aGroup.subject, @"groupId":aGroup.groupId, @"username":aApplicant, @"groupname":aGroup.subject, @"applyMessage":aReason, @"applyStyle":[NSNumber numberWithInteger:ApplyStyleJoinGroup]}];
    [[ApplyViewController shareController] addNewApply:dic];
    if (self.mainVC) {
//        [self.mainVC setupUntreatedApplyCount];
        [self playSoundAndVibration];
    }
}
//SDK自动同意了用户A的加B入群邀请后，用户B接收到该回调，需要设置EMOptions的isAutoAcceptGroupInvitation为YES
- (void)didJoinedGroup:(EMGroup *)aGroup
               inviter:(NSString *)aInviter
               message:(NSString *)aMessage
{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:[NSString stringWithFormat:@"你已成功加入群聊: [%@]",aGroup.subject] delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
    [alertView show];
}

- (void)didReceiveDeclinedJoinGroup:(NSString *)aGroupId
                             reason:(NSString *)aReason
{
    if (!aReason || aReason.length == 0) {
        aReason = [NSString stringWithFormat:NSLocalizedString(@"group.beRefusedToJoin", @"be refused to join the group\'%@\'"), aGroupId];
    }
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:aReason delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
    [alertView show];
}

- (void)didReceiveAcceptedJoinGroup:(EMGroup *)aGroup
{
    NSString *message = [NSString stringWithFormat:NSLocalizedString(@"group.agreedAndJoined", @"agreed to join the group of \'%@\'"), aGroup.subject];
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompt", @"Prompt") message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
    [alertView show];
}
//群主同意用户A的入群申请后，用户A会接收到该回调，群的类型是EMGroupStylePublicJoinNeedApproval
- (void)didReceiveGroupInvitation:(NSString *)aGroupId
                          inviter:(NSString *)aInviter
                          message:(NSString *)aMessage
{
    if (!aGroupId || !aInviter) {
        return;
    }
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:@{@"title":@"", @"groupId":aGroupId, @"username":aInviter, @"groupname":@"", @"applyMessage":aMessage, @"applyStyle":[NSNumber numberWithInteger:ApplyStyleGroupInvitation]}];
    [[ApplyViewController shareController] addNewApply:dic];
    if (self.mainVC) {
//        [self.mainVC setupUntreatedApplyCount];
        [self playSoundAndVibration];
    }
}

#pragma mark - EMContactManagerDelegate
- (void)didReceiveAgreedFromUsername:(NSString *)aUsername
{
    NSString *msgstr = [NSString stringWithFormat:@"%@同意了加好友申请", aUsername];
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:msgstr delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
}

- (void)didReceiveDeclinedFromUsername:(NSString *)aUsername
{
    NSString *msgstr = [NSString stringWithFormat:@"%@拒绝了加好友申请", aUsername];
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:msgstr delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alertView show];
}

- (void)didReceiveDeletedFromUsername:(NSString *)aUsername
{
    NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:_mainVC.navigationController.viewControllers];
    ChatViewController *chatViewContrller = nil;
    for (id viewController in viewControllers)
    {
        if ([viewController isKindOfClass:[ChatViewController class]] && [aUsername isEqualToString:[(ChatViewController *)viewController conversation].conversationId])
        {
            chatViewContrller = viewController;
            break;
        }
    }
    if (chatViewContrller)
    {
        [viewControllers removeObject:chatViewContrller];
        if ([viewControllers count] > 0) {
            [_mainVC.navigationController setViewControllers:@[viewControllers[0]] animated:YES];
        } else {
            [_mainVC.navigationController setViewControllers:viewControllers animated:YES];
        }
    }
    [_mainVC showHint:[NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"delete", @"delete"), aUsername]];
}

- (void)didReceiveAddedFromUsername:(NSString *)aUsername
{
    
}
//用户B申请加A为好友后，用户A会收到这个回调。
//工作圈中应该没有用到这个功能
- (void)didReceiveFriendInvitationFromUsername:(NSString *)aUsername
                                       message:(NSString *)aMessage
{
    if (!aUsername) {
        return;
    }
    
    if (!aMessage) {
        aMessage = [NSString stringWithFormat:NSLocalizedString(@"friend.somebodyAddWithName", @"%@ add you as a friend"), aUsername];
    }
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:@{@"title":aUsername, @"username":aUsername, @"applyMessage":aMessage, @"applyStyle":[NSNumber numberWithInteger:ApplyStyleFriend]}];
    [[ApplyViewController shareController] addNewApply:dic];
    if (self.mainVC) {
//        [self.mainVC setupUntreatedApplyCount];
        [self playSoundAndVibration];
        
        BOOL isAppActivity = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive;
        if (!isAppActivity) {
            //发送本地推送
            if (NSClassFromString(@"UNUserNotificationCenter")) {
                UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
                UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
                content.sound = [UNNotificationSound defaultSound];
                content.body =[NSString stringWithFormat:NSLocalizedString(@"friend.somebodyAddWithName", @"%@ add you as a friend"), aUsername];
                UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[[NSNumber numberWithDouble:[NSDate timeIntervalSinceReferenceDate] * 1000] stringValue] content:content trigger:trigger];
                [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:nil];
            }
            else {
                UILocalNotification *notification = [[UILocalNotification alloc] init];
                notification.fireDate = [NSDate date]; //触发通知的时间
                notification.alertBody = [NSString stringWithFormat:NSLocalizedString(@"friend.somebodyAddWithName", @"%@ add you as a friend"), aUsername];
                notification.alertAction = NSLocalizedString(@"open", @"Open");
                notification.timeZone = [NSTimeZone defaultTimeZone];
            }
            
        }
    }
}

#pragma mark - EMChatroomManagerDelegate 用不到

#pragma mark - EMCallManagerDelegate

//接收到拨打
- (void)callDidReceive:(EMCallSession *)aSession
{
    if ([EaseSDKHelper shareHelper].isShowingimagePicker) {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"hideImagePicker" object:nil];
    }
    
    NSString *callId = @"";
    if (aSession && aSession.callId) {
        callId = [aSession callId];
    }
    
    if(self.callSession && self.callSession.status != EMCallSessionStatusDisconnected){
        [[EMClient sharedClient].callManager endCall:aSession.callId reason:EMCallEndReasonBusy];
        return;
    }
    
    self.callSession = aSession;
    if(self.callSession){
        [self _startCallTimer];
        
        @synchronized (_callLock) {
            self.callController = [[CallViewController alloc] initWithSession:self.callSession isCaller:NO status:NSLocalizedString(@"call.connecting", "Incoimg call")];
            self.callController.modalPresentationStyle = UIModalPresentationOverFullScreen;
            [self.callController _beginRing];//来电时响铃
            dispatch_async(dispatch_get_main_queue(), ^{
                if (self.callController) {
                    BOOL isExit = [self isChatViewController];
                    if (isExit) {//记录当前页面是否是chatVC
                        self.callController.isChatVC = YES;
                    }else {
                        self.callController.isChatVC = NO;
                    }
#warning 一般选择tabBarController弹出，此处先用conversationListVC
                    if (self.mainVC) {
                        [self.mainVC presentViewController:self.callController animated:NO completion:nil];
                    }else if(self.conversationListVC){
                        [self.conversationListVC presentViewController:self.callController animated:NO completion:nil];
                    }else {
                        [self.chatVC presentViewController:self.callController animated:NO completion:nil];
                    }
                }
            });
        }
    }
}
//是否存在聊天界面
- (BOOL)isChatViewController {
    
    NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:_mainVC.navigationController.viewControllers];
    for (UIViewController *viewController in viewControllers)
    {
        if ([viewController isKindOfClass:[ChatViewController class]])
        {
            return YES;
        }
    }
    return NO;
}

//已经连接，通话通道建立完成（双方都走这个方法）
- (void)callDidConnect:(EMCallSession *)aSession
{
    if ([aSession.callId isEqualToString:self.callSession.callId]) {
        NSString *callId = @"";
        if (aSession && aSession.callId) {
            callId = [aSession callId];
        }
        [self.callController stateToConnected];//call.finished
    }
}

//告诉拨打的人已成功被对方接通
- (void)callDidAccept:(EMCallSession *)aSession
{
    if ([aSession.callId isEqualToString:self.callSession.callId]) {
        NSString *callId = @"";
        if (aSession && aSession.callId) {
            callId = [aSession callId];
        }
        
        [self _stopCallTimer];
        [self.callController stateToAnswered];
        if (aSession.type == EMCallTypeVideo) {
            [self.callController answerUI];//对方成功接通后，自己这边重设下UI
        }
    }
}

// *  1. 用户A或用户B结束通话后，对方 会收到该回调
//*  2. 通话出现错误，双方都会收到该回调
- (void)callDidEnd:(EMCallSession *)aSession
            reason:(EMCallEndReason)aReason
             error:(EMError *)aError
{
    NSString *callId = @"";
    if (aSession && aSession.callId) {
        callId = [aSession callId];
    }
    
    if ([aSession.callId isEqualToString:_callSession.callId]) {
        [self _stopCallTimer];
        
        @synchronized (_callLock) {
            if (self.callController && aReason == EMCallEndReasonHangup) {
                [self.callController _stopRing];//停止响铃和震动
                //当对方挂断时（已接通）
                NSString *str = [NSString stringWithFormat:@"%u",aSession.status];
                if (aSession.type == EMCallTypeVoice) {
                    if ([str intValue] == 4) {
                        if ([self isChatViewController]) {
                            self.callController.isChatVC = YES;
                        }
                        [self.callController sendCallMsg:@"[语音通话] 已结束"];
                        
                    } else {
                        if ([self isChatViewController]) {
                            self.callController.isChatVC = YES;
                        }
                        [self.callController sendCallMsg:@"对方已挂断"];
                    }
                }
                else if (aSession.type == EMCallTypeVideo) {
                    if ([str intValue] == 4) {
                        if ([self isChatViewController]) {
                            self.callController.isChatVC = YES;
                        }
                        [self.callController sendCallMsg:@"[视频通话] 已结束"];
                    } else {
                        if ([self isChatViewController]) {
                            self.callController.isChatVC = YES;
                        }
                        [self.callController sendCallMsg:@"对方已挂断"];
                    }
                }
            }
            if (aReason == EMCallEndReasonNoResponse) {//当对方无响应时
                if (self.callController) {
                    [self.callController _stopRing];//停止响铃和震动
                }
            }
            self.callSession = nil;
            [self dismissCurrentCallController];//对方挂断
        }
        
        if (aReason != EMCallEndReasonHangup) {
            NSString *reasonStr = @"";
            switch (aReason) {
                case EMCallEndReasonNoResponse:
                {
                    reasonStr = NSLocalizedString(@"call.noResponse", @"NO response");//对方没有回应
                }
                    break;
                case EMCallEndReasonDecline:
                {
                    reasonStr = NSLocalizedString(@"call.rejected", @"Reject the call");//拒接通话
                }
                    break;
                case EMCallEndReasonBusy:
                {
                    reasonStr = NSLocalizedString(@"call.in", @"In the call...");//正在通话中
                }
                    break;
                case EMCallEndReasonFailed:
                {
                    reasonStr = NSLocalizedString(@"call.connectFailed", @"Connect failed");//建立连接失败
                }
                    break;
                case EMCallEndReasonUnsupported:
                {
                    reasonStr = NSLocalizedString(@"call.connectUnsupported", @"Unsupported");//功能不支持
                }
                    break;
                case EMCallEndReasonRemoteOffline:
                {
                    reasonStr = NSLocalizedString(@"call.offline", @"Remote offline");//对方不在线
                }
                    break;
                default:
                    break;
            }
            
            if (aError) {
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:aError.errorDescription delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
                [alertView show];
            }
            else{
                if (_chatVC == nil) {
                    _chatVC = [self _getCurrentChatView];
                }
                [self.chatVC sendCallMsg:reasonStr];
            }
        }
    }
}
- (void)callNetworkDidChange:(EMCallSession *)aSession status:(EMCallNetworkStatus)aStatus{
    if ([aSession.callId isEqualToString:self.callSession.callId]) {
        [self.callController setNetwork:aStatus];
    }
}

#pragma mark - public

- (void)makeCall:(NSNotification*)notify
{
    if (notify.object) {
        EMCallType type = (EMCallType)[[notify.object objectForKey:@"type"] integerValue];
        [self makeCallWithUsername:[notify.object valueForKey:@"chatter"] type:type];
    }
}

- (void)_startCallTimer
{
    _callTimer = [NSTimer scheduledTimerWithTimeInterval:50 target:self selector:@selector(_cancelCall) userInfo:nil repeats:NO];
}

- (void)_stopCallTimer
{
    if (_callTimer == nil) {
        return;
    }
    
    [_callTimer invalidate];
    _callTimer = nil;
}

- (void)_cancelCall
{
    [self hangupCallWithReason:EMCallEndReasonNoResponse];
    
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"无人接听" delegate:self cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
    [alertView show];
}
//更新call的配置
+ (void)updateCallOptions
{
    NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"calloptions.data"];
    EMCallOptions *options = [[EMClient sharedClient].callManager getCallOptions];
    [NSKeyedArchiver archiveRootObject:options toFile:file];
}
//主动去call
- (void)makeCallWithUsername:(NSString *)aUsername
                        type:(EMCallType)aType
{
    if ([aUsername length] == 0) {
        return;
    }
    
    __weak typeof(self) weakSelf = self;
    void (^completionBlock)(EMCallSession *, EMError *) = ^(EMCallSession *aCallSession, EMError *aError){
        ChatDemoHelper *strongSelf = weakSelf;
        if (strongSelf) {
            if (aError || aCallSession == nil) {
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"call.initFailed", @"Establish call failure") delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
                [alertView show];
                return;
            }
            
            @synchronized (self.callLock) {
                self.callSession = aCallSession;
                self.callController = [[CallViewController alloc] initWithSession:self.callSession isCaller:YES status:NSLocalizedString(@"call.connecting", @"Connecting...")];
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (self.callController) {
                        self.callController.isChatVC = YES;
#warning 一般选择tabBarController弹出，此处先用conversationListVC
                        if (self.mainVC) {
                            [self.mainVC presentViewController:self.callController animated:NO completion:nil];
                        }else if(self.conversationListVC){
                            [self.conversationListVC presentViewController:self.callController animated:NO completion:nil];
                        }else {
                            [self.chatVC presentViewController:self.callController animated:NO completion:nil];
                        }
                    }
                });
            }
            
            [self _startCallTimer];
        }
        else {
            [[EMClient sharedClient].callManager endCall:aCallSession.callId reason:EMCallEndReasonNoResponse];
        }
    };
    
//        [[EMClient sharedClient].callManager startVideoCall:aUsername completion:^(EMCallSession *aCallSession, EMError *aError) {
//            completionBlock(aCallSession, aError);
//        }];
//    }
//    else {
//        [[EMClient sharedClient].callManager startVoiceCall:aUsername completion:^(EMCallSession *aCallSession, EMError *aError) {
//            completionBlock(aCallSession, aError);
//        }];
//    }
    [[EMClient sharedClient].callManager startCall:aType remoteName:aUsername ext:@"123" completion:^(EMCallSession *aCallSession, EMError *aError) {
        completionBlock(aCallSession,aError);
    }];
}

- (void)hangupCallWithReason:(EMCallEndReason)aReason
{
    [self _stopCallTimer];
    
    EMCallSession *tmpSession = self.callSession;
    if (tmpSession) {
        [[EMClient sharedClient].callManager endCall:tmpSession.callId reason:aReason];//结束通话
    }
    
    @synchronized (_callLock) {
        self.callSession = nil;
        [self dismissCurrentCallController];//自己主动挂断
    }
}

- (void)answerCall:(NSString *)aCallId
{
    if (_callSession && [_callSession.callId isEqualToString:aCallId]) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            EMError *error = [[EMClient sharedClient].callManager answerIncomingCall:self.callSession.callId];
            if (error) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (error.code == EMErrorNetworkUnavailable) {
                        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:NSLocalizedString(@"network.disconnection", @"Network disconnection") delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
                        [alertView show];
                    }
                    else{
                        [self hangupCallWithReason:EMCallEndReasonFailed];
                    }
                });
            }
        });
    }
}

- (void)dismissCurrentCallController
{
    self.callController.isDismissing = YES;
    CallViewController *tmpController = self.callController;
    self.callController = nil;
    if (tmpController) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [tmpController dismissViewControllerAnimated:NO completion:nil];
        });
        
        [tmpController clear];
        tmpController = nil;
    }
}

#pragma mark - private
- (BOOL)_needShowNotification:(NSString *)fromChatter
{
    BOOL ret = YES;
    NSArray *igGroupIds = [[EMClient sharedClient].groupManager getGroupsWithoutPushNotification:nil];
    for (NSString *str in igGroupIds) {
        if ([str isEqualToString:fromChatter]) {
            ret = NO;
            break;
        }
    }
    return ret;
}

- (ChatViewController*)_getCurrentChatView
{
    NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:_mainVC.navigationController.viewControllers];
    ChatViewController *chatViewContrller = nil;
    for (id viewController in viewControllers)
    {
        if ([viewController isKindOfClass:[ChatViewController class]])
        {
            chatViewContrller = viewController;
            break;
        }
    }
    return chatViewContrller;
}

- (void)_clearHelper
{
    self.mainVC = nil;
    self.conversationListVC = nil;
    self.chatVC = nil;
    [[EMClient sharedClient] logout:NO];
    [self hangupCallWithReason:EMCallEndReasonFailed];
}
#pragma mark -- 判断来消息的人是否需要静音
//
- (BOOL)isSlientForMessageFromUser:(NSString *)from{
    
    HXDDUserEntity *fromeUser = [[HXRuntimeStatus instance] GetUserForName:from];
    if ([fromeUser.isBeer isEqualToString:@"1"]) {
        return YES;
    }
    return NO;
    //或者从本地数据库中获取
}
//接收到“@”信息之后的处理
//- (void)_handleReceivedAtMessage:(EMMessage*)aMessage
//{
//    if (aMessage.chatType != EMChatTypeGroupChat || aMessage.direction != EMMessageDirectionReceive) {
//        return;
//    }
//    
//    NSString *loginUser = [EMClient sharedClient].currentUsername;
//    NSDictionary *ext = aMessage.ext;
//    EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:aMessage.conversationId type:EMConversationTypeGroupChat createIfNotExist:NO];
//    if (loginUser && conversation && ext && [ext objectForKey:kGroupMessageAtList]) {
//        id target = [ext objectForKey:kGroupMessageAtList];
//        if ([target isKindOfClass:[NSString class]] && [(NSString*)target compare:kGroupMessageAtAll options:NSCaseInsensitiveSearch] == NSOrderedSame) {
//            NSNumber *atAll = conversation.ext[kHaveUnreadAtMessage];
//            if ([atAll intValue] != kAtAllMessage) {
//                NSMutableDictionary *conversationExt = conversation.ext ? [conversation.ext mutableCopy] : [NSMutableDictionary dictionary];
//                [conversationExt removeObjectForKey:kHaveUnreadAtMessage];
//                [conversationExt setObject:@kAtAllMessage forKey:kHaveUnreadAtMessage];
//                conversation.ext = conversationExt;
//            }
//        }
//        else if ([target isKindOfClass:[NSArray class]]) {
//            if ([target containsObject:loginUser]) {
//                if (conversation.ext[kHaveUnreadAtMessage] == nil) {
//                    NSMutableDictionary *conversationExt = conversation.ext ? [conversation.ext mutableCopy] : [NSMutableDictionary dictionary];
//                    [conversationExt setObject:@kAtYouMessage forKey:kHaveUnreadAtMessage];
//                    conversation.ext = conversationExt;
//                }
//            }
//        }
//    }
//}
/*******//*******//*******//*******//*******//*******//*******//*******/
/*******//*******//*******//*******//*******//*******//*******//*******/
#warning 原mainViewController文件，可以移植过来
#pragma mark -- 原mainViewController文件，可以移植过来
// 统计未读消息数
-(void)setupUnreadMessageCount
{
    NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations];
    NSInteger unreadCount = 0;
    for (EMConversation *conversation in conversations) {
        unreadCount += conversation.unreadMessagesCount;
    }
#warning 当tabBar需要显示未读消息的数量时，可以改变这里 self
//    if (unreadCount > 0) {
//        self.tabBarItem.badgeValue = [NSString stringWithFormat:@"%i",(int)unreadCount];
//    }else{
//        self.tabBarItem.badgeValue = nil;
//    }
    
    UIApplication *application = [UIApplication sharedApplication];
    [application setApplicationIconBadgeNumber:unreadCount];
}
- (void)playSoundAndVibration{
    
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < kDefaultPlaySoundInterval) {
        //如果距离上次响铃和震动时间太短, 则跳过响铃
        NSLog(@"skip ringing & vibration %@, %@", [NSDate date], self.lastPlaySoundDate);
        return;
    }
    
    //保存最后一次响铃时间
    self.lastPlaySoundDate = [NSDate date];
    
    // 收到消息时，播放音频
    [[EMCDDeviceManager sharedInstance] playNewMessageSound];
    // 收到消息时，震动
    [[EMCDDeviceManager sharedInstance] playVibration];
}
- (void)showNotificationWithMessage:(EMMessage *)message
{
    EMPushOptions *options = [[EMClient sharedClient] pushOptions];
    //发送本地推送
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.fireDate = [NSDate date]; //触发通知的时间
    
    if (options.displayStyle == EMPushDisplayStyleMessageSummary) {
        EMMessageBody *messageBody = message.body;
        NSString *messageStr = nil;
        switch (messageBody.type) {
            case EMMessageBodyTypeText:
            {
                messageStr = ((EMTextMessageBody *)messageBody).text;
            }
                break;
            case EMMessageBodyTypeImage:
            {
                messageStr = NSLocalizedString(@"message.image", @"Image");
            }
                break;
            case EMMessageBodyTypeLocation:
            {
                messageStr = NSLocalizedString(@"message.location", @"Location");
            }
                break;
            case EMMessageBodyTypeVoice:
            {
                messageStr = NSLocalizedString(@"message.voice", @"Voice");
            }
                break;
            case EMMessageBodyTypeVideo:{
                messageStr = NSLocalizedString(@"message.video", @"Video");
            }
                break;
            default:
                break;
        }
        
        NSString *title = message.from;
        if (message.chatType == EMChatTypeGroupChat) {
            NSArray *groupArray = [[EMClient sharedClient].groupManager getJoinedGroups];
            for (EMGroup *group in groupArray) {
                if ([group.groupId isEqualToString:message.conversationId]) {
                    title = [NSString stringWithFormat:@"%@(%@)", message.from, group.subject];
                    break;
                }
            }
        }
    }
    else{
        notification.alertBody = NSLocalizedString(@"receiveMessage", @"you have a new message");
    }
    
#warning 去掉注释会显示[本地]开头, 方便在开发中区分是否为本地推送
    //    notification.alertBody = [[NSString alloc] initWithFormat:@"[本地]%@", notification.alertBody];
    
    notification.alertAction = NSLocalizedString(@"open", @"Open");
    notification.timeZone = [NSTimeZone defaultTimeZone];
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < kDefaultPlaySoundInterval) {
        NSLog(@"skip ringing & vibration %@, %@", [NSDate date], self.lastPlaySoundDate);
    } else {
        notification.soundName = UILocalNotificationDefaultSoundName;
        self.lastPlaySoundDate = [NSDate date];
    }
    
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:message.chatType] forKey:kMessageType];
    [userInfo setObject:message.conversationId forKey:kConversationChatter];
    notification.userInfo = userInfo;
    
    //发送通知
    [[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
//#pragma mark - public
//
//- (void)jumpToChatList
//{
//    if ([_mainVC.navigationController.topViewController isKindOfClass:[ChatViewController class]]) {
////                ChatViewController *chatController = (ChatViewController *)self.navigationController.topViewController;
////                [chatController hideImagePicker];
//    }
//    else if(_conversationListVC)
//    {
//        [_mainVC.navigationController popToViewController:_mainVC animated:NO];
//        [_mainVC setSelectedViewController:_conversationListVC];
//    }
//}
//
//- (EMConversationType)conversationTypeFromMessageType:(EMChatType)type
//{
//    EMConversationType conversatinType = EMConversationTypeChat;
//    switch (type) {
//        case EMChatTypeChat:
//            conversatinType = EMConversationTypeChat;
//            break;
//        case EMChatTypeGroupChat:
//            conversatinType = EMConversationTypeGroupChat;
//            break;
//        case EMChatTypeChatRoom:
//            conversatinType = EMConversationTypeChatRoom;
//            break;
//        default:
//            break;
//    }
//    return conversatinType;
//}
//
//- (void)didReceiveLocalNotification:(UILocalNotification *)notification
//{
//    NSDictionary *userInfo = notification.userInfo;
//    if (userInfo)
//    {
//        if ([_mainVC.navigationController.topViewController isKindOfClass:[ChatViewController class]]) {
//            //            ChatViewController *chatController = (ChatViewController *)self.navigationController.topViewController;
//            //            [chatController hideImagePicker];
//        }
//        
//        NSArray *viewControllers = _mainVC.navigationController.viewControllers;
//        [viewControllers enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
//            if (obj != _mainVC)
//            {
//                if (![obj isKindOfClass:[ChatViewController class]])
//                {
//                    [_mainVC.navigationController popViewControllerAnimated:NO];
//                }
//                else
//                {
//                    NSString *conversationChatter = userInfo[kConversationChatter];
//                    ChatViewController *chatViewController = (ChatViewController *)obj;
//                    if (![chatViewController.conversation.conversationId isEqualToString:conversationChatter])
//                    {
//                        [_mainVC.navigationController popViewControllerAnimated:NO];
//                        EMChatType messageType = [userInfo[kMessageType] intValue];
//                        chatViewController = [[ChatViewController alloc] initWithConversationChatter:conversationChatter conversationType:[self conversationTypeFromMessageType:messageType]];
//                        [_mainVC.navigationController pushViewController:chatViewController animated:NO];
//                    }
//                    *stop= YES;
//                }
//            }
//            else
//            {
//                ChatViewController *chatViewController = nil;
//                NSString *conversationChatter = userInfo[kConversationChatter];
//                EMChatType messageType = [userInfo[kMessageType] intValue];
//
//                chatViewController = [[ChatViewController alloc] initWithConversationChatter:conversationChatter conversationType:[self conversationTypeFromMessageType:messageType]];
//
//                [_mainVC.navigationController pushViewController:chatViewController animated:NO];
//            }
//        }];
//    }
//    else if (_conversationListVC)
//    {
//        [_mainVC.navigationController popToViewController:_mainVC animated:NO];
//        [_mainVC setSelectedViewController:_conversationListVC];
//    }
//}
//
//- (void)didReceiveUserNotification:(UNNotification *)notification
//{
//    NSDictionary *userInfo = notification.request.content.userInfo;
//    if (userInfo)
//    {
//        if ([_mainVC.navigationController.topViewController isKindOfClass:[ChatViewController class]]) {
////            ChatViewController *chatController = (ChatViewController *)self.navigationController.topViewController;
////            [chatController hideImagePicker];
//        }
//        
//        NSArray *viewControllers = _mainVC.navigationController.viewControllers;
//        [viewControllers enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
//            if (obj != _mainVC)
//            {
//                if (![obj isKindOfClass:[ChatViewController class]])
//                {
//                    [_mainVC.navigationController popViewControllerAnimated:NO];
//                }
//                else
//                {
//                    NSString *conversationChatter = userInfo[kConversationChatter];
//                    ChatViewController *chatViewController = (ChatViewController *)obj;
//                    if (![chatViewController.conversation.conversationId isEqualToString:conversationChatter])
//                    {
//                        [_mainVC.navigationController popViewControllerAnimated:NO];
//                        EMChatType messageType = [userInfo[kMessageType] intValue];
//                        chatViewController = [[ChatViewController alloc] initWithConversationChatter:conversationChatter conversationType:[self conversationTypeFromMessageType:messageType]];
//                        [_mainVC.navigationController pushViewController:chatViewController animated:NO];
//                    }
//                    *stop= YES;
//                }
//            }
//            else
//            {
//                ChatViewController *chatViewController = nil;
//                NSString *conversationChatter = userInfo[kConversationChatter];
//                EMChatType messageType = [userInfo[kMessageType] intValue];
//
//                chatViewController = [[ChatViewController alloc] initWithConversationChatter:conversationChatter conversationType:[self conversationTypeFromMessageType:messageType]];
//
//                [_mainVC.navigationController pushViewController:chatViewController animated:NO];
//            }
//        }];
//    }
//    else if (_conversationListVC)
//    {
//        [_conversationListVC.navigationController popToViewController:_mainVC animated:NO];
//        [_mainVC setSelectedViewController:_conversationListVC];
//    }
//}

@end
